package com.teacher.game.framework.util;

import android.util.Log;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 内存泄漏检测器 - 监控对象生命周期，检测潜在内存泄漏
 * 帮助发现和定位内存泄漏问题
 */
public class MemoryLeakDetector {
    
    private static final String TAG = "MemoryLeakDetector";
    private static MemoryLeakDetector instance;
    
    // 对象引用跟踪
    private final Map<String, List<WeakReference<Object>>> trackedObjects;
    
    // 内存快照
    private final List<MemorySnapshot> snapshots;
    
    // 检测配置
    private boolean enabled = true;
    private long checkInterval = 10000; // 10秒检查一次
    private long lastCheck = 0;
    private int maxSnapshotCount = 50;
    
    // 统计数据
    private int leakDetectedCount = 0;
    private int objectsTracked = 0;
    private int garbageCollected = 0;
    
    /**
     * 内存快照
     */
    private static class MemorySnapshot {
        public final long timestamp;
        public final long usedMemory;
        public final long totalMemory;
        public final long maxMemory;
        public final int trackedObjectCount;
        
        public MemorySnapshot() {
            this.timestamp = System.currentTimeMillis();
            Runtime runtime = Runtime.getRuntime();
            this.usedMemory = runtime.totalMemory() - runtime.freeMemory();
            this.totalMemory = runtime.totalMemory();
            this.maxMemory = runtime.maxMemory();
            this.trackedObjectCount = 0; // 将在外部设置
        }
    }
    
    /**
     * 私有构造函数
     */
    private MemoryLeakDetector() {
        trackedObjects = new HashMap<>();
        snapshots = new ArrayList<>();
        Log.d(TAG, "内存泄漏检测器已启动");
    }
    
    /**
     * 获取单例实例
     * @return MemoryLeakDetector实例
     */
    public static synchronized MemoryLeakDetector getInstance() {
        if (instance == null) {
            instance = new MemoryLeakDetector();
        }
        return instance;
    }
    
    /**
     * 启用/禁用内存泄漏检测
     * @param enabled 是否启用
     */
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
        Log.d(TAG, "内存泄漏检测" + (enabled ? "已启用" : "已禁用"));
    }
    
    /**
     * 跟踪对象生命周期
     * @param category 对象类别
     * @param object 要跟踪的对象
     */
    public void trackObject(String category, Object object) {
        if (!enabled || object == null) return;
        
        synchronized (trackedObjects) {
            List<WeakReference<Object>> categoryObjects = trackedObjects.get(category);
            if (categoryObjects == null) {
                categoryObjects = new ArrayList<>();
                trackedObjects.put(category, categoryObjects);
            }
            
            categoryObjects.add(new WeakReference<>(object));
            objectsTracked++;
            
            Log.d(TAG, "开始跟踪对象: " + category + " (总数: " + objectsTracked + ")");
        }
    }
    
    /**
     * 停止跟踪对象
     * @param category 对象类别
     * @param object 要停止跟踪的对象
     */
    public void untrackObject(String category, Object object) {
        if (!enabled || object == null) return;
        
        synchronized (trackedObjects) {
            List<WeakReference<Object>> categoryObjects = trackedObjects.get(category);
            if (categoryObjects != null) {
                Iterator<WeakReference<Object>> iterator = categoryObjects.iterator();
                while (iterator.hasNext()) {
                    WeakReference<Object> ref = iterator.next();
                    if (ref.get() == object) {
                        iterator.remove();
                        Log.d(TAG, "停止跟踪对象: " + category);
                        break;
                    }
                }
            }
        }
    }
    
    /**
     * 执行内存泄漏检测
     */
    public void performLeakCheck() {
        if (!enabled) return;
        
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastCheck < checkInterval) {
            return;
        }
        
        Log.d(TAG, "开始内存泄漏检测...");
        
        synchronized (trackedObjects) {
            // 清理已被GC的弱引用
            cleanupWeakReferences();
            
            // 创建内存快照
            MemorySnapshot snapshot = new MemorySnapshot();
            snapshots.add(snapshot);
            
            // 限制快照数量
            while (snapshots.size() > maxSnapshotCount) {
                snapshots.remove(0);
            }
            
            // 分析内存趋势
            analyzeMemoryTrend();
            
            lastCheck = currentTime;
        }
        
        Log.d(TAG, "内存泄漏检测完成");
    }
    
    /**
     * 清理已被GC的弱引用
     */
    private void cleanupWeakReferences() {
        int cleanedCount = 0;
        
        for (Map.Entry<String, List<WeakReference<Object>>> entry : trackedObjects.entrySet()) {
            List<WeakReference<Object>> objects = entry.getValue();
            Iterator<WeakReference<Object>> iterator = objects.iterator();
            
            while (iterator.hasNext()) {
                WeakReference<Object> ref = iterator.next();
                if (ref.get() == null) {
                    iterator.remove();
                    cleanedCount++;
                    garbageCollected++;
                }
            }
        }
        
        if (cleanedCount > 0) {
            Log.d(TAG, "清理了 " + cleanedCount + " 个已回收的对象引用");
        }
    }
    
    /**
     * 分析内存趋势
     */
    private void analyzeMemoryTrend() {
        if (snapshots.size() < 3) return;
        
        // 获取最近3个快照
        int size = snapshots.size();
        MemorySnapshot current = snapshots.get(size - 1);
        MemorySnapshot prev1 = snapshots.get(size - 2);
        MemorySnapshot prev2 = snapshots.get(size - 3);
        
        // 检测内存持续增长
        if (current.usedMemory > prev1.usedMemory && 
            prev1.usedMemory > prev2.usedMemory) {
            
            double growthRate = (double)(current.usedMemory - prev2.usedMemory) / prev2.usedMemory;
            
            if (growthRate > 0.1) { // 内存增长超过10%
                leakDetectedCount++;
                Log.w(TAG, "检测到潜在内存泄漏! 内存增长率: " + 
                      String.format("%.1f%%", growthRate * 100));
                
                // 输出详细信息
                logDetailedMemoryInfo();
            }
        }
    }
    
    /**
     * 输出详细内存信息
     */
    private void logDetailedMemoryInfo() {
        Log.d(TAG, "=== 详细内存信息 ===");
        
        Runtime runtime = Runtime.getRuntime();
        long used = runtime.totalMemory() - runtime.freeMemory();
        long total = runtime.totalMemory();
        long max = runtime.maxMemory();
        
        Log.d(TAG, "当前内存使用: " + formatBytes(used));
        Log.d(TAG, "总分配内存: " + formatBytes(total));
        Log.d(TAG, "最大可用内存: " + formatBytes(max));
        Log.d(TAG, "内存使用率: " + String.format("%.1f%%", (double)used / max * 100));
        
        // 输出跟踪对象统计
        Log.d(TAG, "=== 跟踪对象统计 ===");
        for (Map.Entry<String, List<WeakReference<Object>>> entry : trackedObjects.entrySet()) {
            String category = entry.getKey();
            int count = entry.getValue().size();
            Log.d(TAG, category + ": " + count + " 个对象");
        }
    }
    
    /**
     * 强制执行垃圾回收
     */
    public void forceGarbageCollection() {
        Log.d(TAG, "强制执行垃圾回收...");
        
        // 记录GC前的内存状态
        Runtime runtime = Runtime.getRuntime();
        long beforeGC = runtime.totalMemory() - runtime.freeMemory();
        
        // 执行GC
        System.gc();
        System.runFinalization();
        System.gc();
        
        // 等待一小段时间让GC完成
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        // 记录GC后的内存状态
        long afterGC = runtime.totalMemory() - runtime.freeMemory();
        long freedMemory = beforeGC - afterGC;
        
        Log.d(TAG, "垃圾回收完成，释放内存: " + formatBytes(freedMemory));
        
        // 清理弱引用
        cleanupWeakReferences();
    }
    
    /**
     * 格式化字节数
     * @param bytes 字节数
     * @return 格式化字符串
     */
    private String formatBytes(long bytes) {
        if (bytes < 1024) return bytes + "B";
        if (bytes < 1024 * 1024) return String.format("%.1fKB", bytes / 1024.0f);
        return String.format("%.1fMB", bytes / (1024.0f * 1024.0f));
    }
    
    /**
     * 获取内存泄漏报告
     * @return 内存泄漏报告字符串
     */
    public String getLeakReport() {
        StringBuilder report = new StringBuilder();
        report.append("=== 内存泄漏检测报告 ===\n");
        report.append("检测状态: ").append(enabled ? "启用" : "禁用").append("\n");
        report.append("泄漏检测次数: ").append(leakDetectedCount).append("\n");
        report.append("跟踪对象总数: ").append(objectsTracked).append("\n");
        report.append("已回收对象数: ").append(garbageCollected).append("\n");
        report.append("内存快照数量: ").append(snapshots.size()).append("\n");
        
        // 当前跟踪对象统计
        report.append("\n=== 当前跟踪对象 ===\n");
        synchronized (trackedObjects) {
            for (Map.Entry<String, List<WeakReference<Object>>> entry : trackedObjects.entrySet()) {
                String category = entry.getKey();
                int count = entry.getValue().size();
                report.append(category).append(": ").append(count).append(" 个对象\n");
            }
        }
        
        return report.toString();
    }
    
    /**
     * 获取内存使用统计
     * @return 内存使用统计字符串
     */
    public String getMemoryStats() {
        Runtime runtime = Runtime.getRuntime();
        long used = runtime.totalMemory() - runtime.freeMemory();
        long total = runtime.totalMemory();
        long max = runtime.maxMemory();
        
        return String.format("内存: %s/%s (%.1f%%) | 跟踪: %d对象 | 泄漏: %d次",
            formatBytes(used), formatBytes(max), (double)used / max * 100,
            getTotalTrackedObjects(), leakDetectedCount);
    }
    
    /**
     * 获取当前跟踪对象总数
     * @return 跟踪对象总数
     */
    private int getTotalTrackedObjects() {
        int total = 0;
        synchronized (trackedObjects) {
            for (List<WeakReference<Object>> objects : trackedObjects.values()) {
                total += objects.size();
            }
        }
        return total;
    }
    
    /**
     * 重置统计数据
     */
    public void reset() {
        synchronized (trackedObjects) {
            trackedObjects.clear();
            snapshots.clear();
            leakDetectedCount = 0;
            objectsTracked = 0;
            garbageCollected = 0;
            lastCheck = 0;
        }
        Log.d(TAG, "内存泄漏检测数据已重置");
    }
}